//因为使用过vscode编辑，注释出现编码的问题，删除以后会运行报错，就不删除了
//肖韫然 524031910761 孙佳
#include "Timer.h"
#include "HX711.h"


// ״̬ö��
// 定义枚举类型的三个状态
enum SystemState {
  LOCKED,       // ����״̬
  UNLOCKED,     // ����״̬
  WATER_FLOW    // ��ˮ״̬
};

// ȫ�ֱ���
volatile SystemState currentState = LOCKED;
unsigned long push1PressTime = 0;
unsigned long unlockStartTime = 0;
bool push2Released = true;
// 消抖函数
bool checkButton(int pin) {
  static int lastPUSH1State = HIGH;
  static int lastPUSH2State = HIGH;
  static unsigned long lastDebounceTime = 0;
  const int debounceDelay = 50;
  
  int currentState = digitalRead(pin);
  bool result = false;

  if (pin == PUSH1) {
    if (currentState != lastPUSH1State) {
      lastDebounceTime = millis();
    }
    if ((millis() - lastDebounceTime) > debounceDelay) {
      if (currentState != lastPUSH1State) {
        lastPUSH1State = currentState;
        if (currentState == LOW) result = true;
      }
    }
  } 
  else if (pin == PUSH2) {
    if (currentState != lastPUSH2State) {
      lastDebounceTime = millis();
    }
    if ((millis() - lastDebounceTime) > debounceDelay) {
      if (currentState != lastPUSH2State) {
        lastPUSH2State = currentState;
        if (currentState == LOW) result = true;
      }
    }
  }
  return result;
}
void setup() {
  Serial.begin(9600);  // 初始化串口，波特率9600
  Serial.println("串口已启动，波特率9600");
  pinMode(PUSH1, INPUT_PULLUP); //上拉输入
  pinMode(PUSH2, INPUT_PULLUP); //上拉输入
  pinMode(RED_LED, OUTPUT);     //输出
  pinMode(GREEN_LED, OUTPUT);   //输出

  // ��ʼ״̬�������
  digitalWrite(RED_LED, HIGH);  //初始化红灯亮
  digitalWrite(GREEN_LED, LOW); //初始化绿灯亮
}

void loop() {
  handleStateMachine();     //内部寄存器运算
  updateLEDs();             //驱动LED
}

void handleStateMachine(void) {//内部寄存器运算
  switch (currentState) {   //检查当前状态
    case LOCKED:             //如果是LOCKED
      Serial.println("LOCKED");
      handleLockedState();   //执行解锁中断，是否能解锁在函数里验证
      break;

    case UNLOCKED:           //如果是UNLOCKED
      Serial.println("UNLOCKED");
      handleUnlockedState(); //执行上锁中断
      break;

    case WATER_FLOW:         //如果在出水
      Serial.println("WATER_FLOW");
      handleWaterFlowState();
      break;
  }
}

void handleLockedState(void) {                 //童锁上锁期间
  // ��ⳤ��PUSH1 3��
  if (digitalRead(PUSH1) == LOW ) {            //当被按下童锁
    if (digitalRead(PUSH2) == HIGH && push1PressTime != 1) {          //当热水键没被按下
      Serial.println("PUSH1_PRESSED") ;
      if (push1PressTime == 0) {                //如果按下时间为0
        push1PressTime = millis();              //将当前时间记录到push1PressTime里
        Serial.println(push1PressTime);
      }
      if (millis() - push1PressTime >= 6000) {  //当长按住超过6s，
        currentState = UNLOCKED;                //解锁，
        unlockStartTime = millis();             //将解锁的时间记录到unlockStartTime里，
        push1PressTime = 0;                     //把push1PressTime计时清零
      }
    } else {
      push1PressTime = 1;                        /用来判定是不是之前同时按下过两个push键。因为重复可能性很小
      Serial.println("PUSH1&PUSH2_PRESSED") ;   //童锁和热水键都被按下
      }
    } else {
      push1PressTime = 0;                       //当童锁没被按下，保持按下时间为0
      if(digitalRead(PUSH2) == LOW){
        Serial.println("PUSH2_PRESSED") ;
      }
  }
}

void handleUnlockedState(void) {                 //童锁打开期间
  // 3�볬ʱ���
  if (digitalRead(PUSH2) == HIGH){
    if (digitalRead(PUSH2) == HIGH && !push2Released) { //检测到热水键被按了一下
      push2Released = true;                             //更新热水键状态为松开
      currentState = WATER_FLOW;                        //机器状态改为放热水
      return;
    }
    else if (millis() - unlockStartTime >= 3000) {    //当解锁时间超过三秒
      currentState = LOCKED;                     //将状态转变成LOCKED
      return;}
  }
  // ����PUSH2�ͷ��¼�
  if (digitalRead(PUSH2) == HIGH && !push2Released) { //检测到热水键被按了一下
    push2Released = true;                             //更新热水键状态为松开
    currentState = WATER_FLOW;                        //机器状态改为放热水
  }

  // ���°���״̬
  if (digitalRead(PUSH2) == LOW) {                    //读取热水键是低电平
    push2Released = false;                            //热水键被按住记录状态
  }
}

void handleWaterFlowState(void) {                        //放热水期间
  if (digitalRead(PUSH1)==LOW) Serial.println("PUSH1_PRESSED_WHILE_WATER_FLOW");
  // ����PUSH2�ͷ��¼�
  if (digitalRead(PUSH2) == HIGH && !push2Released) {//检测到热水键被按了一下
    push2Released = true;                            //更新热水键状态为松开
    currentState = LOCKED;                           //机器状态改为锁住
  }
  // ���°���״̬
  if (digitalRead(PUSH2) == LOW) {                   //如果热水键是低电平，
    push2Released = false;                           //热水键状态是被按住
  }

  // ����PUSH1����
}

void updateLEDs(void) {                   //驱动LED
  switch (currentState) {
    case LOCKED:                      //童锁状态下
      digitalWrite(RED_LED, HIGH);    //红灯亮，绿灯暗
      digitalWrite(GREEN_LED, LOW);
      break;

    case UNLOCKED:                     //解锁状态下
      digitalWrite(RED_LED, LOW);      //都不亮
      digitalWrite(GREEN_LED, LOW);
      break;

    case WATER_FLOW:                    //放水状态下
      digitalWrite(RED_LED, LOW);       //红灯暗，绿灯亮
      digitalWrite(GREEN_LED, HIGH);
      break;
  }
}
